home *** CD-ROM | disk | FTP | other *** search
-
- While working of a port of "lpr/lpd" to Windows95 I noticed some
- weaknesses in the implementation of the LPR protocol. Mostly it
- appears to affect BSD based UNIX's. I found it using the source for
- BSD4.4, and tested it on "Linux Slackware 2.2.0". I have also tested it
- on AIX 4.1.5 and it seems to be OK. Unfortunately, (or Fortunately
- depending on how you look at it), I only have access to these two
- operating systems.
-
- Explaining this assumes that you are familiar with [RFC-1179 Line Pinter
- Daemon Protocol]. If you are not familiar or have not read it, it may
- be obtained via FTP from ftp://nic.ddn.mil/rfc/rfc1179.txt
-
- The possibilities are as follows:
- 1.) Obtaining hard (or possibly soft) copies of any file on the system.
- 2.) Deleting any file on the system.
- 3.) Creating a file on the system.
- 4.) Mail bombing.
-
- There are a few requirements that need to be met in order to perform
- these actions.
- 1.) Must be 'root' on the source machine.
- NOTE: Under Windows95 the user already has 'root' status. This means
- that anyone on a Win95 box
- can bind network sockets to the reserved ports.
- 2.) Must have or obtain permission to print to the target machine.
- Usually machines on the same network will have permission to print to
- each other, but that may not always be the case.
- 3.) Must have or obtain access to the target printer. Otherwise how
- will you get your printout?
-
- HOW IT WORKS...
-
- When lpd sends a file to a remote machine it creates a control file used
- to instruct the remote machine on how to process the incoming print
- job. These commands are outlined in [RFC-1179]. It is the
- implementation of the control commands that provide the weakness.
-
- 1.) Obtaining hard (or possibly soft) copies of any file on the system.
- The control command 'f' causes a file to be printed as text.
-
- The syntax is: f filename [LF]
-
- Therefore, by inserting the line: "f/etc/shadow" into the control file
- you will cause the
- Shadow password file to be printed. (Hard copy)
-
- If the print queue points to a network printer then it would be possible
- to capture the packets. (Soft copy)
-
- 2.) Delete any file on the system.
- The control command 'U' instructs the remote machine to "unlink" the
- file upon completion of the job.
-
- The syntax is: U filename [LF]
-
- Therefore, by inserting the line: "U/vmlinuz" into the control file you
- will cause the Linux kernel to be
- removed from the file system.
-
- 3.) Create a file on the remote system.
- This is a little trickier, in that BSD4.4 takes the filename that you
- specify and appends its view of the calling machine's hostname to it.
- However, BSD4.4 starts at the sixth character.
-
- The syntax is 2 size [SP] filename [LF]. Where '2' is the octet 2 not
- the character, size is the size of the file in bytes, filename is ...
- (DUH).
-
- - From RECVJOB.C
- case '\2': /* read cf file */
- size = 0;
- while (*cp >= '0' && *cp <= '9')
- size = size * 10 + (*cp++ - '0');
- if (*cp++ != ' ')
- break;
- /*
- * host name has been authenticated, we use our
- * view of the host name since we may be passed
- * something different than what gethostbyaddr()
- * returns
- */
- HERE -----------> strcpy(cp + 6, from);
- strcpy(tfname, cp);
- tfname[0] = 't';
- if (!chksize(size)) {
- (void) write(1, "\2", 1);
- continue;
- }
- if (!readfile(tfname, size)) {
- rcleanup(0);
- continue;
- }
- if (link(tfname, cp) < 0)
- frecverr("%s: %m", tfname);
- (void) unlink(tfname);
- tfname[0] = '\0';
- nfiles++;
- continue;
-
- The result is this:
-
- /rc becomes /rc
- /etc/passwd becomes /etc/passwd.www.yourhost.com
-
- This is accomplished by using the printer command of '2' (receive
- control file)
-
- Therefore by sending the printer command '2/rc' and then sending our
- file, we have created a file in the root directory called 'rc'.
- By sending '2/home/yourfriend/somefile' and the your file you will have
- sent somefile to yourfriend ... and even put it in their home
- directory. Of course it will have the name somefile.www.yourhost.com,
- but he got it none the less.
-
- 4.) Mail bombing.
- The control command 'M' instructs lpd to mail the user when the job is
- finished.
-
- The syntax is: M username [LF]
-
- Therefore by adding the line: "Mjoeuser@www.somewhere.com" you will
- cause joeuser to receive mail notification about the print job. By
- adding several thousand of these lines, well you get the idea.
-
- SOLUTIONS ???
- These holes are due to the implementation of the lpr protocol and the
- fact that lpd runs as root. I am sure that there may be many solutions
- to this, but At first glance I think that by checking for a '/' in the
- filenames would cause the program to react when someone tries to print
- files from outside of the queue directory.
-
- As far as the mail bomb, maybe by checking the destination host with
- lpd's view of the caller, but that wouldn't allow for someone to print
- from one account and get the mail at another. IE the boss getting
- notices when the report is finished.
-
- Let me know if I have miss-stated something.
-
- Bennett
-
- ---------------------------------------------------------------------------
-
-
- > 1.) Obtaining hard (or possibly soft) copies of any file on the system.
- > 2.) Deleting any file on the system.
- > 3.) Creating a file on the system.
- > 4.) Mail bombing.
-
- 5.) Overflow at least one buffer from the network; this is just
- above the "print any file" part of recvjob.c:
-
- cp = line;
- do {
- if ((size = read(1, cp, 1)) != 1) {
- if (size < 0)
- frecverr("%s: Lost connection",printer);
- return(nfiles);
- }
- } while (*cp++ != '\n');
-
- Consequences aren't really obvious, but you may be able to do
- nasty things.
-
- Will we ever get rid of gets()? (lpd source tree is from some
- recent RedHat distribution.)
-
-
- ----------------------------------------------------------------------------
-
- >
- >On October 02 1997, Bennett Samowich wrote:
- >
- >> 1.) Obtaining hard (or possibly soft) copies of any file on the system.
- >> 2.) Deleting any file on the system.
- >> 3.) Creating a file on the system.
- >> 4.) Mail bombing.
- >
- >5.) Overflow at least one buffer from the network; this is just
- >above the "print any file" part of recvjob.c:
- >
- > cp = line;
- > do {
- > if ((size = read(1, cp, 1)) != 1) {
- > if (size < 0)
- > frecverr("%s: Lost connection",printer);
- > return(nfiles);
- > }
- > } while (*cp++ != '\n');
- >
- >
- >Consequences aren't really obvious, but you may be able to do
- >nasty things.
- >
- >Will we ever get rid of gets()? (lpd source tree is from some
- >recent RedHat distribution.)
-
- Here's another one from common_source/common.c
- while ((c = getc(cfp)) != '\n') {
- if (c == EOF)
- return(0);
- if (c == '\t') {
- do {
- *lp++ = ' ';
- linel++;
- } while ((linel & 07) != 0);
- continue;
- }
- *lp++ = c;
- linel++;
- }
- *lp++ = '\0';
- return(linel);
-
- A fix would appear to be to make the while like this:
- while ((c = getc(cfp)) != '\n' && linel < BUFSIZ-8) {
-
- Why BUFSIZ-8?
- leave space for tab expansion in inner do loop. It still should be
- a plenty long enough buffer. Or, add another check for linel in
- inner do loop.
-
- ----------------------------------------------------------------------------
-